using Microsoft.Extensions.Logging;
using System.Diagnostics;
using System.Text;
using Uantek.Device.Communication.Models;
using Uantek.Device.Communication.Protocols.Interfaces;

namespace Uantek.Device.Communication.Protocols.Base
{
    /// <summary>
    /// 设备协议基类
    /// </summary>
    public abstract class BaseDeviceProtocol : IDeviceProtocol
    {
        /// <summary>
        /// 日志记录器
        /// </summary>
        protected readonly ILogger? _logger;

        /// <summary>
        /// 协议名称
        /// </summary>
        public abstract string ProtocolName { get; }

        /// <summary>
        /// 协议版本
        /// </summary>
        public abstract string Version { get; }

        /// <summary>
        /// 数据接收事件
        /// </summary>
        public event EventHandler<DeviceDataModel>? DataReceived;

        /// <summary>
        /// 状态变化事件
        /// </summary>
        public event EventHandler<DeviceStatus>? StatusChanged;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="logger">日志记录器</param>
        protected BaseDeviceProtocol(ILogger? logger = null)
        {
            _logger = logger;
        }

        /// <summary>
        /// 解析设备数据
        /// </summary>
        /// <param name="rawData">原始数据</param>
        /// <returns>解析后的设备数据</returns>
        public virtual async Task<DeviceDataModel?> ParseDeviceDataAsync(byte[] rawData)
        {
            var stopwatch = Stopwatch.StartNew();
            try
            {
                LogDebug("开始解析设备数据，协议: {ProtocolName}，数据长度: {Length}", ProtocolName, rawData.Length);

                if (rawData == null || rawData.Length == 0)
                {
                    LogWarning("原始数据为空");
                    return null;
                }

                // 验证数据完整性
                if (!ValidateData(rawData))
                {
                    LogWarning("数据验证失败");
                    return null;
                }

                // 调用具体实现的解析方法
                var result = await ParseDataAsync(rawData);

                if (result != null)
                {
                    result.Timestamp = DateTime.Now;
                    result.ProtocolName = ProtocolName;
                    result.ProtocolVersion = Version;
                    result.RawData = BitConverter.ToString(rawData);

                    LogDebug("设备数据解析成功，协议: {ProtocolName}，数据类型: {DataType}，耗时: {ElapsedMs}ms", 
                        ProtocolName, result.DataType, stopwatch.ElapsedMilliseconds);
                }
                else
                {
                    LogWarning("设备数据解析失败，协议: {ProtocolName}", ProtocolName);
                }

                return result;
            }
            catch (Exception ex)
            {
                LogError(ex, "解析设备数据时发生异常，协议: {ProtocolName}", ProtocolName);
                return null;
            }
            finally
            {
                stopwatch.Stop();
            }
        }

        /// <summary>
        /// 构建命令数据
        /// </summary>
        /// <param name="command">命令</param>
        /// <param name="parameters">参数</param>
        /// <returns>命令数据</returns>
        public virtual async Task<byte[]> BuildCommandAsync(string command, Dictionary<string, object>? parameters = null)
        {
            var stopwatch = Stopwatch.StartNew();
            try
            {
                LogDebug("开始构建命令，协议: {ProtocolName}，命令: {Command}", ProtocolName, command);

                if (string.IsNullOrWhiteSpace(command))
                {
                    throw new ArgumentException("命令不能为空", nameof(command));
                }

                // 调用具体实现的命令构建方法
                var commandData = await BuildCommandDataAsync(command, parameters);

                LogDebug("命令构建成功，协议: {ProtocolName}，命令: {Command}，数据长度: {Length}，耗时: {ElapsedMs}ms", 
                    ProtocolName, command, commandData.Length, stopwatch.ElapsedMilliseconds);

                return commandData;
            }
            catch (Exception ex)
            {
                LogError(ex, "构建命令时发生异常，协议: {ProtocolName}，命令: {Command}", ProtocolName, command);
                throw;
            }
            finally
            {
                stopwatch.Stop();
            }
        }

        /// <summary>
        /// 验证数据完整性
        /// </summary>
        /// <param name="data">数据</param>
        /// <returns>是否有效</returns>
        public virtual bool ValidateData(byte[] data)
        {
            try
            {
                if (data == null || data.Length == 0)
                {
                    LogWarning("数据为空");
                    return false;
                }

                // 调用具体实现的验证方法
                var isValid = ValidateDataInternal(data);

                if (isValid)
                {
                    LogDebug("数据验证成功，协议: {ProtocolName}，数据长度: {Length}", ProtocolName, data.Length);
                }
                else
                {
                    LogWarning("数据验证失败，协议: {ProtocolName}，数据长度: {Length}", ProtocolName, data.Length);
                }

                return isValid;
            }
            catch (Exception ex)
            {
                LogError(ex, "验证数据时发生异常，协议: {ProtocolName}", ProtocolName);
                return false;
            }
        }

        /// <summary>
        /// 获取支持的传输类型
        /// </summary>
        /// <returns>支持的传输类型列表</returns>
        public abstract IEnumerable<string> GetSupportedTransportTypes();

        /// <summary>
        /// 连接设备
        /// </summary>
        /// <returns>连接结果</returns>
        public virtual async Task<CommunicationResult> ConnectAsync()
        {
            try
            {
                LogInformation("开始连接设备，协议: {ProtocolName}", ProtocolName);
                
                var result = await ConnectDeviceAsync();
                
                if (result.Success)
                {
                    LogInformation("设备连接成功，协议: {ProtocolName}", ProtocolName);
                }
                else
                {
                    LogWarning("设备连接失败，协议: {ProtocolName}，错误: {Message}", ProtocolName, result.Message);
                }
                
                return result;
            }
            catch (Exception ex)
            {
                LogError(ex, "设备连接时发生异常，协议: {ProtocolName}", ProtocolName);
                return CommunicationResult.Failed($"连接异常: {ex.Message}");
            }
        }

        /// <summary>
        /// 断开设备连接
        /// </summary>
        /// <returns>断开结果</returns>
        public virtual async Task<CommunicationResult> DisconnectAsync()
        {
            try
            {
                LogInformation("开始断开设备连接，协议: {ProtocolName}", ProtocolName);
                
                var result = await DisconnectDeviceAsync();
                
                if (result.Success)
                {
                    LogInformation("设备断开成功，协议: {ProtocolName}", ProtocolName);
                }
                else
                {
                    LogWarning("设备断开失败，协议: {ProtocolName}，错误: {Message}", ProtocolName, result.Message);
                }
                
                return result;
            }
            catch (Exception ex)
            {
                LogError(ex, "设备断开时发生异常，协议: {ProtocolName}", ProtocolName);
                return CommunicationResult.Failed($"断开异常: {ex.Message}");
            }
        }

        /// <summary>
        /// 发送命令
        /// </summary>
        /// <param name="command">命令</param>
        /// <param name="parameters">参数</param>
        /// <returns>命令执行结果</returns>
        public virtual async Task<CommunicationResult<string>> SendCommandAsync(string command, Dictionary<string, object>? parameters = null)
        {
            try
            {
                LogInformation("开始发送命令，协议: {ProtocolName}，命令: {Command}", ProtocolName, command);
                
                var result = await SendDeviceCommandAsync(command, parameters);
                
                if (result.Success)
                {
                    LogInformation("命令发送成功，协议: {ProtocolName}，命令: {Command}", ProtocolName, command);
                }
                else
                {
                    LogWarning("命令发送失败，协议: {ProtocolName}，命令: {Command}，错误: {Message}", ProtocolName, command, result.Message);
                }
                
                return result;
            }
            catch (Exception ex)
            {
                LogError(ex, "发送命令时发生异常，协议: {ProtocolName}，命令: {Command}", ProtocolName, command);
                return CommunicationResult<string>.Failed($"发送异常: {ex.Message}");
            }
        }

        /// <summary>
        /// 释放资源
        /// </summary>
        public virtual void Dispose()
        {
            try
            {
                LogInformation("释放资源，协议: {ProtocolName}", ProtocolName);
                DisposeInternal();
            }
            catch (Exception ex)
            {
                LogError(ex, "释放资源时发生异常，协议: {ProtocolName}", ProtocolName);
            }
        }

        #region 抽象方法 - 由子类实现

        /// <summary>
        /// 解析数据的具体实现
        /// </summary>
        /// <param name="rawData">原始数据</param>
        /// <returns>解析后的设备数据</returns>
        protected abstract Task<DeviceDataModel?> ParseDataAsync(byte[] rawData);

        /// <summary>
        /// 构建命令数据的具体实现
        /// </summary>
        /// <param name="command">命令</param>
        /// <param name="parameters">参数</param>
        /// <returns>命令数据</returns>
        protected abstract Task<byte[]> BuildCommandDataAsync(string command, Dictionary<string, object>? parameters);

        /// <summary>
        /// 验证数据完整性的具体实现
        /// </summary>
        /// <param name="data">数据</param>
        /// <returns>是否有效</returns>
        protected abstract bool ValidateDataInternal(byte[] data);

        /// <summary>
        /// 连接设备的具体实现
        /// </summary>
        /// <returns>连接结果</returns>
        protected abstract Task<CommunicationResult> ConnectDeviceAsync();

        /// <summary>
        /// 断开设备连接的具体实现
        /// </summary>
        /// <returns>断开结果</returns>
        protected abstract Task<CommunicationResult> DisconnectDeviceAsync();

        /// <summary>
        /// 发送设备命令的具体实现
        /// </summary>
        /// <param name="command">命令</param>
        /// <param name="parameters">参数</param>
        /// <returns>命令执行结果</returns>
        protected abstract Task<CommunicationResult<string>> SendDeviceCommandAsync(string command, Dictionary<string, object>? parameters);

        /// <summary>
        /// 释放资源的具体实现
        /// </summary>
        protected virtual void DisposeInternal()
        {
            // 默认实现，子类可重写
        }

        #endregion

        #region 受保护的辅助方法

        /// <summary>
        /// 触发数据接收事件
        /// </summary>
        /// <param name="data">设备数据</param>
        protected virtual void OnDataReceived(DeviceDataModel data)
        {
            try
            {
                DataReceived?.Invoke(this, data);
            }
            catch (Exception ex)
            {
                LogError(ex, "触发数据接收事件时发生异常");
            }
        }

        /// <summary>
        /// 触发状态变化事件
        /// </summary>
        /// <param name="status">设备状态</param>
        protected virtual void OnStatusChanged(DeviceStatus status)
        {
            try
            {
                StatusChanged?.Invoke(this, status);
            }
            catch (Exception ex)
            {
                LogError(ex, "触发状态变化事件时发生异常");
            }
        }

        /// <summary>
        /// 记录调试信息
        /// </summary>
        /// <param name="message">消息</param>
        /// <param name="args">参数</param>
        protected void LogDebug(string message, params object[] args)
        {
            _logger?.LogDebug(message, args);
        }

        /// <summary>
        /// 记录信息
        /// </summary>
        /// <param name="message">消息</param>
        /// <param name="args">参数</param>
        protected void LogInformation(string message, params object[] args)
        {
            _logger?.LogInformation(message, args);
        }

        /// <summary>
        /// 记录警告信息
        /// </summary>
        /// <param name="message">消息</param>
        /// <param name="args">参数</param>
        protected void LogWarning(string message, params object[] args)
        {
            _logger?.LogWarning(message, args);
        }

        /// <summary>
        /// 记录错误信息
        /// </summary>
        /// <param name="ex">异常</param>
        /// <param name="message">消息</param>
        /// <param name="args">参数</param>
        protected void LogError(Exception ex, string message, params object[] args)
        {
            _logger?.LogError(ex, message, args);
        }

        /// <summary>
        /// 记录错误信息
        /// </summary>
        /// <param name="message">消息</param>
        /// <param name="args">参数</param>
        protected void LogError(string message, params object[] args)
        {
            _logger?.LogError(message, args);
        }

        /// <summary>
        /// 将字节数组转换为十六进制字符串
        /// </summary>
        /// <param name="bytes">字节数组</param>
        /// <returns>十六进制字符串</returns>
        protected static string BytesToHex(byte[] bytes)
        {
            if (bytes == null || bytes.Length == 0)
                return string.Empty;

            return Convert.ToHexString(bytes);
        }

        /// <summary>
        /// 将十六进制字符串转换为字节数组
        /// </summary>
        /// <param name="hex">十六进制字符串</param>
        /// <returns>字节数组</returns>
        protected static byte[] HexToBytes(string hex)
        {
            if (string.IsNullOrWhiteSpace(hex))
                return Array.Empty<byte>();

            // 移除空格和常见分隔符
            hex = hex.Replace(" ", "").Replace("-", "").Replace(":", "");

            // 确保长度为偶数
            if (hex.Length % 2 != 0)
                hex = "0" + hex;

            var bytes = new byte[hex.Length / 2];
            for (int i = 0; i < bytes.Length; i++)
            {
                bytes[i] = Convert.ToByte(hex.Substring(i * 2, 2), 16);
            }

            return bytes;
        }

        /// <summary>
        /// 计算CRC16校验码（Modbus RTU使用）
        /// </summary>
        /// <param name="data">数据</param>
        /// <returns>CRC16校验码</returns>
        protected static ushort CalculateCrc16(byte[] data)
        {
            if (data == null || data.Length == 0)
                return 0;

            ushort crc = 0xFFFF;
            for (int i = 0; i < data.Length; i++)
            {
                crc ^= data[i];
                for (int j = 0; j < 8; j++)
                {
                    if ((crc & 1) == 1)
                        crc = (ushort)((crc >> 1) ^ 0xA001);
                    else
                        crc = (ushort)(crc >> 1);
                }
            }
            return crc;
        }

        /// <summary>
        /// 计算LRC校验码（Modbus ASCII使用）
        /// </summary>
        /// <param name="data">数据</param>
        /// <returns>LRC校验码</returns>
        protected static byte CalculateLrc(byte[] data)
        {
            if (data == null || data.Length == 0)
                return 0;

            byte lrc = 0;
            foreach (byte b in data)
            {
                lrc += b;
            }
            return (byte)((lrc ^ 0xFF) + 1);
        }

        /// <summary>
        /// 交换字节序（大端序与小端序转换）
        /// </summary>
        /// <param name="value">16位值</param>
        /// <returns>交换后的值</returns>
        protected static ushort SwapBytes(ushort value)
        {
            return (ushort)((value << 8) | (value >> 8));
        }

        /// <summary>
        /// 交换字节序（大端序与小端序转换）
        /// </summary>
        /// <param name="value">32位值</param>
        /// <returns>交换后的值</returns>
        protected static uint SwapBytes(uint value)
        {
            return (value << 24) | ((value << 8) & 0x00FF0000) |
                   ((value >> 8) & 0x0000FF00) | (value >> 24);
        }

        /// <summary>
        /// 将16位值转换为大端序字节数组
        /// </summary>
        /// <param name="value">16位值</param>
        /// <returns>大端序字节数组</returns>
        protected static byte[] UInt16ToBigEndianBytes(ushort value)
        {
            return new byte[] { (byte)(value >> 8), (byte)(value & 0xFF) };
        }

        /// <summary>
        /// 将32位值转换为大端序字节数组
        /// </summary>
        /// <param name="value">32位值</param>
        /// <returns>大端序字节数组</returns>
        protected static byte[] UInt32ToBigEndianBytes(uint value)
        {
            return new byte[] 
            { 
                (byte)(value >> 24), 
                (byte)((value >> 16) & 0xFF), 
                (byte)((value >> 8) & 0xFF), 
                (byte)(value & 0xFF) 
            };
        }

        /// <summary>
        /// 从大端序字节数组转换为16位值
        /// </summary>
        /// <param name="bytes">字节数组</param>
        /// <param name="offset">偏移量</param>
        /// <returns>16位值</returns>
        protected static ushort BigEndianBytesToUInt16(byte[] bytes, int offset = 0)
        {
            if (bytes == null || bytes.Length < offset + 2)
                throw new ArgumentException("字节数组长度不足");

            return (ushort)((bytes[offset] << 8) | bytes[offset + 1]);
        }

        /// <summary>
        /// 从大端序字节数组转换为32位值
        /// </summary>
        /// <param name="bytes">字节数组</param>
        /// <param name="offset">偏移量</param>
        /// <returns>32位值</returns>
        protected static uint BigEndianBytesToUInt32(byte[] bytes, int offset = 0)
        {
            if (bytes == null || bytes.Length < offset + 4)
                throw new ArgumentException("字节数组长度不足");

            return (uint)((bytes[offset] << 24) | (bytes[offset + 1] << 16) | 
                         (bytes[offset + 2] << 8) | bytes[offset + 3]);
        }

        /// <summary>
        /// 位操作：获取指定位的值
        /// </summary>
        /// <param name="value">值</param>
        /// <param name="bitIndex">位索引（0-15）</param>
        /// <returns>位值</returns>
        protected static bool GetBit(ushort value, int bitIndex)
        {
            if (bitIndex < 0 || bitIndex > 15)
                throw new ArgumentOutOfRangeException(nameof(bitIndex), "位索引必须在0-15之间");

            return (value & (1 << bitIndex)) != 0;
        }

        /// <summary>
        /// 位操作：设置指定位的值
        /// </summary>
        /// <param name="value">值</param>
        /// <param name="bitIndex">位索引（0-15）</param>
        /// <param name="bitValue">位值</param>
        /// <returns>设置后的值</returns>
        protected static ushort SetBit(ushort value, int bitIndex, bool bitValue)
        {
            if (bitIndex < 0 || bitIndex > 15)
                throw new ArgumentOutOfRangeException(nameof(bitIndex), "位索引必须在0-15之间");

            if (bitValue)
                return (ushort)(value | (1 << bitIndex));
            else
                return (ushort)(value & ~(1 << bitIndex));
        }

        /// <summary>
        /// 数据类型转换：将浮点数转换为Modbus寄存器格式
        /// </summary>
        /// <param name="value">浮点数</param>
        /// <returns>寄存器数组</returns>
        protected static ushort[] FloatToModbusRegisters(float value)
        {
            var bytes = BitConverter.GetBytes(value);
            if (BitConverter.IsLittleEndian)
            {
                Array.Reverse(bytes);
            }
            
            return new ushort[]
            {
                BigEndianBytesToUInt16(bytes, 0),
                BigEndianBytesToUInt16(bytes, 2)
            };
        }

        /// <summary>
        /// 数据类型转换：将Modbus寄存器格式转换为浮点数
        /// </summary>
        /// <param name="registers">寄存器数组</param>
        /// <returns>浮点数</returns>
        protected static float ModbusRegistersToFloat(ushort[] registers)
        {
            if (registers == null || registers.Length < 2)
                throw new ArgumentException("寄存器数组长度不足");

            var bytes = new byte[4];
            var reg1Bytes = UInt16ToBigEndianBytes(registers[0]);
            var reg2Bytes = UInt16ToBigEndianBytes(registers[1]);
            
            bytes[0] = reg1Bytes[0];
            bytes[1] = reg1Bytes[1];
            bytes[2] = reg2Bytes[0];
            bytes[3] = reg2Bytes[1];

            if (BitConverter.IsLittleEndian)
            {
                Array.Reverse(bytes);
            }

            return BitConverter.ToSingle(bytes, 0);
        }

        /// <summary>
        /// 格式化字节数组为可读字符串
        /// </summary>
        /// <param name="bytes">字节数组</param>
        /// <param name="separator">分隔符</param>
        /// <param name="maxLength">最大显示长度</param>
        /// <returns>格式化字符串</returns>
        protected static string FormatBytes(byte[] bytes, string separator = " ", int maxLength = 50)
        {
            if (bytes == null || bytes.Length == 0)
                return string.Empty;

            var sb = new StringBuilder();
            var displayLength = Math.Min(bytes.Length, maxLength);

            for (int i = 0; i < displayLength; i++)
            {
                if (i > 0)
                    sb.Append(separator);
                sb.AppendFormat("{0:X2}", bytes[i]);
            }

            if (bytes.Length > maxLength)
            {
                sb.Append("...");
            }

            return sb.ToString();
        }

        /// <summary>
        /// 验证数据长度
        /// </summary>
        /// <param name="data">数据</param>
        /// <param name="expectedLength">期望长度</param>
        /// <returns>是否匹配</returns>
        protected bool ValidateDataLength(byte[] data, int expectedLength)
        {
            if (data == null)
            {
                LogWarning("数据为空");
                return false;
            }

            if (data.Length != expectedLength)
            {
                LogWarning("数据长度不匹配，期望: {Expected}，实际: {Actual}", expectedLength, data.Length);
                return false;
            }

            return true;
        }

        /// <summary>
        /// 验证数据长度范围
        /// </summary>
        /// <param name="data">数据</param>
        /// <param name="minLength">最小长度</param>
        /// <param name="maxLength">最大长度</param>
        /// <returns>是否在范围内</returns>
        protected bool ValidateDataLengthRange(byte[] data, int minLength, int maxLength)
        {
            if (data == null)
            {
                LogWarning("数据为空");
                return false;
            }

            if (data.Length < minLength || data.Length > maxLength)
            {
                LogWarning("数据长度超出范围，范围: {Min}-{Max}，实际: {Actual}", minLength, maxLength, data.Length);
                return false;
            }

            return true;
        }

        #endregion
    }
}